package kpi.java_training.utils;

import kpi.java_training.domain.questions.Question;
import kpi.java_training.domain.questions.QuestionData;
import kpi.java_training.domain.questions.Topic;
import static kpi.java_training.utils.XmlConstants.*;

import kpi.java_training.users.User;
import kpi.java_training.users.UsersList;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.List;

/**
 * Created by Alex Kebkalo (kebka@mail.ru) on 26.11.13.
 * Provides methods to save data to xml file. Data includes questions, answers and users
 */
public class DomDataSaver {
    private String fileName;
    private Document document;

    public DomDataSaver(String fileName) throws Exception {
        this.fileName = fileName;
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        document = docBuilder.newDocument();
    }

    // TODO: refactor
    public void saveTeachingData(List<Topic> topics, List<String> answers) throws Exception {
        Element rootElement = document.createElement(USER);
        document.appendChild(rootElement);
        addQuestions(rootElement, topics);
        addAnswers(rootElement, answers);

        checkFile();
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource domSource = new DOMSource(document);
        StreamResult streamResult = new StreamResult(new File(fileName).getAbsolutePath());

        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.transform(domSource, streamResult);
    }

    // TODO: refactor
    public void saveUserData(UsersList users) throws Exception {
        Element rootElement = document.createElement(USERS_SECTION);
        document.appendChild(rootElement);
        addUsers(rootElement, users);

        checkFile();
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource domSource = new DOMSource(document);
        StreamResult streamResult = new StreamResult(new File(fileName).getAbsolutePath());

        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.transform(domSource, streamResult);
    }

    private void addUsers(Element rootElement, UsersList users) {
        for (int i=0; i < users.size(); i++) {
            rootElement.appendChild(generateUserElement(users.getUser(i)));
        }
    }

    private Element generateUserElement(User user) {
        Element userElement = document.createElement(USER);

        Element element = document.createElement(USER_NAME);
        element.appendChild(document.createTextNode(user.getLogin()));
        userElement.appendChild(element);

        element = document.createElement(USER_PASSWORD);
        element.appendChild(document.createTextNode(user.getPassword()));
        userElement.appendChild(element);

        return userElement;
    }

    private void checkFile() throws Exception {
        File f = new File(fileName);
        if (f.exists()) {
            f.delete();
        }
    }

    private void addQuestions(Element rootElement, List<Topic> topics) {
        Element questionsElement = document.createElement(QUESTIONS_SECTION);
        rootElement.appendChild(questionsElement);
        for (Topic topic : topics) {
            Element topicElement = document.createElement(TOPIC);
            questionsElement.appendChild(topicElement);

            Element topicNameElement = document.createElement(TOPIC_NAME);
            topicNameElement.appendChild(document.createTextNode(topic.getTopicName()));
            topicElement.appendChild(topicNameElement);

            for (int i=0; i < topic.size(); i++) {
                topicElement.appendChild(generateQuestionElement(topic.getQuestion(i)));
            }
        }
    }



    private Element generateQuestionElement(Question question) {
        Element questionElement = document.createElement(QUESTION);
        QuestionData questionData = question.getSaveData();

        Element element = document.createElement(QUESTION_TYPE);
        element.appendChild(document.createTextNode(questionData.type));
        questionElement.appendChild(element);

        element = document.createElement(QUESTION_TEXT);
        element.appendChild(document.createTextNode(questionData.textOfQuestion));
        questionElement.appendChild(element);

        element = document.createElement(ANSWER_VARIANTS);
        for (String s : questionData.answerVariants) {
            Element element1 = document.createElement(ANSWER_VARIANT);
            element1.appendChild(document.createTextNode(s));
            element.appendChild(element1);
        }
        questionElement.appendChild(element);


        element = document.createElement(CORRECT_ANSWER);
        element.appendChild(document.createTextNode(questionData.correctAnswer));
        questionElement.appendChild(element);

        element = document.createElement(COMPLEXITY);
        element.appendChild(document.createTextNode(questionData.complexity));
        questionElement.appendChild(element);

        return questionElement;
    }

    private void addAnswers(Element rootElement, List<String> answers) {
        Element answersElement = document.createElement(ANSWERS_SECTION);
        rootElement.appendChild(answersElement);
        for (String answer : answers) {
            Element element = document.createElement(ANSWER);
            element.appendChild(document.createTextNode(answer));
            answersElement.appendChild(element);
        }
    }
}
